import { Component, Vue } from 'vue-property-decorator'
import mapboxgl from 'mapbox-gl'
import mapUtils from '@/components/gis/map-package/map-utils'
import CoordinatesControl from '@/components/gis/map-package/map-controls/coordinates-control'

@Component({})
export default class GisMixin extends Vue {
  public mapBox: any = null // 实例化地图
  public layerList: any[] = [] // 地图图层列表
  public layerData: any = {} // 图层数据 geojson
  // mapbox gl 气泡框
  public mapboxPopup: any = new mapboxgl.Popup({
    closeButton: false,
    closeOnClick: false,
  })
  // 鼠标经纬度位置
  public coordinatesControl: any = new CoordinatesControl({
    decimal: 4, // 经纬度精度
  })
  // 比例尺
  public mapScale = new mapboxgl.ScaleControl({
    maxWidth: 120, // 比例尺控制的最大长度,默认100，以像素为单位
    unit: 'metric', // 单位，分为 'imperial', 'metric','nautical' 三种类型，默认为 'metric'
  })

  public addCoordinatesControl() {
    this.mapBox.addControl(this.coordinatesControl, 'bottom-left')
  }
  public addMapScaleControl() {
    this.mapBox.addControl(this.mapScale, 'bottom-left')
  }

  /**
   * 地图存在的图层id
   */
  public exitLayerIds() {
    const exitLayerIds: string[] = []
    if (this.mapBox) {
      this.layerList.forEach((layer: any) => {
        const mapLayer = this.mapBox.getLayer(String(layer.id))
        if (mapLayer) {
          exitLayerIds.push(String(layer.id))
        }
      })
    }
    return exitLayerIds
  }

  /**
   * 初始化/更新地图鼠标移动事件
   */
  public initAndUpdateMapboxOnMouseEvent() {
    this.mapBox.off('mousemove', ($event: any) => this.globalMouseEvent($event))
    this.mapBox.on('mousemove', ($event: any) => this.globalMouseEvent($event))
  }

  /**
   * 图层要素要显示的字段
   * @param layerId
   */
  public getLayerAttributeTagOfDetailByLayerId(layerId: string): string[] {
    const currentLayer: any = this.layerList.find(
      (layer: any) => layer.id === Number(layerId)
    )
    if (
      currentLayer.data?.tagInfo?.attributeTag &&
      currentLayer.data.tagInfo.attributeTag.length > 0
    ) {
      const detailField: string[] = currentLayer.data.tagInfo.attributeTag
        .filter((tag: any) => tag.tagType === 'detail')
        .map((tag: any) => tag.name)
      return [...new Set(detailField)]
    }
    return []
  }

  /**
   * 地图全局鼠标事件
   * @param $event
   */
  public globalMouseEvent($event: any) {
    const features = this.mapBox.queryRenderedFeatures($event.point, {
      layers: this.exitLayerIds(),
    })
    // 其他不高亮
    if (features.length > 0) {
      const [firstLayerFeature, ...otherLayerFeatures] = features
      if (otherLayerFeatures.length > 0) {
        otherLayerFeatures.forEach((feature: any) => {
          this.mapBox.setFeatureState(
            { source: `source-${feature.layer.id}`, id: feature.id },
            { hover: false }
          )
        })
      }

      $event.preventDefault()
      this.mapBox.getCanvas().style.cursor = 'pointer'
      const coordinates = firstLayerFeature.geometry.coordinates.slice()
      const currentFeatureProperty: any = firstLayerFeature.properties
      // delete currentFeatureProperty._record_id_
      const popupShowFields: string[] = this.getLayerAttributeTagOfDetailByLayerId(
        firstLayerFeature.layer.id
      )
      if (popupShowFields.length > 0) {
        let attributesDom = ''
        popupShowFields.forEach((key: any) => {
          attributesDom += `<div class="attr-key-value">${key}: ${currentFeatureProperty[key]}</div>`
        })
        while (Math.abs($event.lngLat.lng - coordinates[0]) > 180) {
          coordinates[0] += $event.lngLat.lng > coordinates[0] ? 360 : -360
        }
        this.mapboxPopup
          .setLngLat($event.lngLat)
          .setHTML(`<div>${attributesDom}</div>`)
          .setMaxWidth('300px')
          .addTo(this.mapBox)
      } else {
        this.mapboxPopup.remove()
      }
    }
  }

  /**
   * 初始化添加空图层
   */
  public initAddEmpty() {
    const emptyLayerExist = this.mapBox.getLayer('base-empty-layer')
    if (!emptyLayerExist) {
      const layerInfo: any = {
        id: 'base-empty-layer',
        type: 'fill',
        source: {
          type: 'geojson',
          data: null,
        },
      }
      this.mapBox.addLayer(layerInfo)
    }
  }

  /**
   * 地图图层添加鼠标事件 （移除气泡框）
   */
  public addMouseEventToMapBoxByLayerId(layerId: string) {
    this.mapBox.on('mouseleave', layerId, () => {
      this.mapBox.getCanvas().style.cursor = ''
      this.mapboxPopup.remove()
    })
  }

  /**
   * 添加点
   */
  public addPoint(layer: any, beforeId: string) {
    mapUtils.addPoint(this.mapBox, layer, beforeId)
  }

  /**
   * 添加线
   */
  public addLine(layer: any, beforeId: string) {
    mapUtils.addLine(this.mapBox, layer, beforeId)
    if (layer.data?.hasArrow && layer.visible === 1) {
      this.addArrowLayer(layer, beforeId)
    }
  }

  public addArrowLayer(layer: any, beforeId: string) {
    const layerDataInfo: any = this.layerData[layer.id] || { geojson: null }
    const { geojson } = layerDataInfo
    mapUtils.addArrowLayerByLineLayer(this.mapBox, layer, geojson, beforeId)
  }

  /**
   * 添加面
   */
  public addPolygon(layer: any, beforeId: string) {
    mapUtils.addPolygon(this.mapBox, layer, beforeId)
  }
}
